-- up
MSG_REGISTER = 0x0100
MSG_HEART = 0x0002
MSG_UNREGISTER = 0x0003
MSG_AUTH = 0x0102
MSG_POSITION = 0x0200
MSG_BATCH_POSITION = 0x0704

MSG_GENERAL_RESPONSE = 0x0001

-- down
MSG_SERVER_RESPONSE = 0x8001
MSG_SERVER_REGIST_RESPONSE = 0x8100
MSG_SERVER_CONTROL_DEV = 0x8105
MSG_SERVER_CONTROL_CAR = 0x8500

JT808_HEADER = 0x7e

-- JT/T 808-2019
JT_VERSION_FLAG = 0x4000
JT_SPLIT = 0x0
JT_ENCRYPT = 0x0

JT_VERSION = 0x1

JT808_MAX = 1024

local msg_num = 0
local phone = "13360516231"
local province = 37
local city = 125
local company = "cnostar"
local model = "CT10"
local SN = "2325001"
local color = 1
local car_id = "B52VP8"
local auth_str = "013360516231"
local imei = "864269068614664"
local sw_ver = "V1.0"

local untranfer_flag = 0

local jt808_buff
local jt808_parser = {}

local pvt_lat = 22
local pvt_lon = 113
local pvt_time = "221230183100"
local pvt_alt=22
local pvt_speed = 0
local pvt_course = 0

local phone_len = 6
local phone_bcd_len = 12

local phone_num = zbuff.create(phone_len, 0x0)
local transfer_flag = 0

local header_buff = zbuff.create(17)



--[[
1.心跳:
终端请求： 7e000200000857502162890001c67e
7e # 标识位
000200000857502162890001 # 消息头
    0002 # 消息ID
    0000 # 消息体属性，消息体属性每个位都为零,也即第12-15位的消息包封装项不存在,消息体也为空
    085750216289 # 终端手机号或设备号,这里是设备号
    0001 # 流水号
c6 # 校验码
7e # 标识位
]] --

function print_zbuff(d)
    str = ""
    str = str .. string.format("%x:", d:used())
    for i = 0, d:used() - 1 do str = str .. string.format("%02x", d[i]) end
    print(str)
end

function load_param()
    --  local phone = nil--fdb.kv_get("phone_num")
    if phone == nil then phone = "17620356231" end
    local l = string.len(phone)
    local phone20 = "00000000000000000000"
    local n = 0

    if l > phone_bcd_len then
        phone = string.sub(phone, 1, phone_bcd_len)
    else
        phone = string.sub(phone20, 1, phone_bcd_len - l) .. phone
    end
    l = string.len(phone)
    for i = 1, l, 2 do
        hnum = tonumber(string.sub(phone, i, i), 16)
        lnum = tonumber(string.sub(phone, i + 1, i + 1), 16)

        num = hnum * 0x10 + lnum
        -- print(string.format("%d %02x", i, num))
        phone_num:writeU8(num)
    end

    --  province = fdb.kv_get("province")
    --  city = fdb.kv_get("city")
    --  company = fdb.kv_get("company")
    --  model = fdb.kv_get("model")
    --  SN = fdb.kv_get("SN")
    --  color = fdb.kv_get("color")
    --  car_id = fdb.kv_get("car_id")
    --  auth_str = fdb.kv_get("auth")
end

function header(msg_id, msg_len)
    header_buff:seek(0)
    header_buff:pack(">HH", msg_id, JT_SPLIT + JT_ENCRYPT + msg_len)
    header_buff:copy(nil, phone_num)
    header_buff:pack(">H", msg_num)
    msg_num = msg_num + 1
    if msg_num > 65535 then msg_num = 0 end
    return header_buff;
end

function proc_crc(indata, start, len)
    local crc = 0
    for i = start, len - 1 do crc = bit.bxor(crc, indata[i]) end
    return crc
end

function transfer(indata, len)
    local outdata = zbuff.create(len * 2)
    local str = ""
    for i = 0, len - 1 do
        if indata[i] == 0x7d then
            outdata:writeU8(0x7d);
            outdata:writeU8(0x01);
            -- outdata[j] = 0x01;
        elseif indata[i] == 0x7e then
            outdata:writeU8(0x7d);
            outdata:writeU8(0x02);
        else
            outdata:writeU8(indata[i])
        end
    end
    return outdata
end

-- a package include 0x7e
function untransfer(indata, len)
    local outdata = zbuff.create(len)
    for i = 1, len - 2 do
        local v = indata[i]
        if transfer_flag == 0x7d then
            if v == 0x01 then
                outdata:writeU8(0x7d)
            elseif v == 0x02 then
                outdata:writeU8(0x7e)
            else
                print("error trans")
            end
            transfer_flag = 0x0
        elseif v == 0x7d then
            transfer_flag = v;
        else
            outdata:writeU8(v)
        end
    end
    return outdata
end

function jt808_MSG_SERVER_REGIST_RESPONSE(indata)
    print("jt808_MSG_SERVER_REGIST_RESPONSE")
    ret = indata[19]
    auth_str = indata:query(20, indata:used() - 20)
    print(auth_str)
    print_zbuff(indata)
end

function init_jt808()
    jt808_buff = zbuff.create(JT808_MAX, 0)
    jt808_parser[MSG_SERVER_RESPONSE] = nil
    jt808_parser[MSG_SERVER_REGIST_RESPONSE] = jt808_MSG_SERVER_REGIST_RESPONSE
    jt808_parser[MSG_SERVER_CONTROL_DEV] = nil
    jt808_parser[MSG_SERVER_CONTROL_CAR] = nil
end

function input_jt808(indata)
    len = indata:used() - 1
    for i = 0, len do
        v = indata[i]
        if jt808_buff:used() == 0 then
            if v == JT808_HEADER then
                jt808_buff:seek(0)
                jt808_buff:writeU8(v)
            end
            goto continue
        end

        if jt808_buff:used() == JT808_MAX then
            print("too long")
            jt808_buff:seek(0)
            goto continue
        end

        jt808_buff:writeU8(v)
        --    print(jt808_buff:used())
        --    print(v)

        if v == JT808_HEADER then
            if jt808_buff:used() < 10 then
                print("too short")
                jt808_buff:seek(0)
                jt808_buff:writeU8(v)
                goto continue
            else
                a = untransfer(jt808_buff, jt808_buff:used())
                -- print_zbuff(a)
                crc = proc_crc(a, 0, a:used())
                if crc ~= 0x00 then
                    print("crc error")
                    jt808_buff:seek(0)
                    jt808_buff:writeU8(v)
                    goto continue
                end
                print("find a pkg")

                cmd = a:query(0, 2, true)

                -- MSG_SERVER_REGIST_RESPONSE
                local parser = jt808_parser[cmd]
                if parser ~= nil then parser(a) end
                jt808_buff:seek(0)
            end
        end

        ::continue::
    end
end

--[[
2.注册包：
终端注册-请求：7e0100002e0188554850150025002c0133373039363054372d54383038000000000000000000000000003033323931373001e6b599413636363636557e
7e # 标识位
0100002e0188554850150025 # 消息头
    0100 # 消息ID
    002e # 消息体属性，消息体属性每个位都为零,也即第12-15位的消息包封装项不存在,消息体也为空
    018855485015 # 终端手机号或设备号,这里是设备号
    0025 # 流水号
002c0133373039363054372d54383038000000000000000000000000003033323931373001e6b599413636363636 # 消息体
    002c # 省份id
	0133 # 城市id
	3730393630 # 制造商id
	54372d5438303800000000000000000000000000 # 终端型号
	30333239313730 # 终端id
	01 # 车牌颜色
	e6b599413636363636 # 车牌标识
55 # 校验码
7e # 标识位
]] --

function jt808_register()
    local body = zbuff.create(100, 0)
    body:pack(">H", province)
    body:pack(">H", city)
    body:write(company)
    body:seek(9)
    body:write(model)
    body:seek(17)
    body:write(SN)
    body:seek(24)
    body:writeU8(color)
    body:write(car_id)

    local h = header(MSG_REGISTER, body:used())
    -- !!!copy will resize the zbuff
    h:copy(nil, body)

    --  crc = proc_crc(h, 0, h:used())
    --  print(crc)
    -- !!!bug
    if h:used() == h:len() then h:resize(h:len() + 10) end

    h:writeU8(proc_crc(h, 0, h:used()))

    local msg = transfer(h, h:used())

    local msgall = zbuff.create(msg:used() + 2, 0)
    msgall:writeU8(0x7e)
    msgall:copy(nil, msg)
    msgall:writeU8(0x7e)
    --  print_zbuff(msgall)

    return msgall
end

function jt808_heart()
    local h = header(MSG_HEART, 0)
    crc = proc_crc(h, 0, h:used())
    h:resize(20)
    h:writeU8(crc)

    local msg = transfer(h, h:used())

    local msgall = zbuff.create(msg:used() + 2, 0)
    msgall:writeU8(0x7e)
    msgall:copy(nil, msg)
    msgall:writeU8(0x7e)
    --  print_zbuff(msgall)

    return msgall
end

function jt808_auth()
    local body = zbuff.create(100, 0)
    body:writeU8(auth_str:len())
    body:write(auth_str)
    body:write(imei)
    body:seek(auth_str:len() + 16)
    body:write(sw_ver)
    body:seek(auth_str:len() + 36)

    local h = header(MSG_AUTH, body:used())
    -- !!!copy will resize the zbuff
    h:copy(nil, body)

    --  crc = proc_crc(h, 0, h:used())
    --  print(crc)
    -- !!!bug
    if h:used() == h:len() then h:resize(h:len() + 10) end

    h:writeU8(proc_crc(h, 0, h:used()))

    local msg = transfer(h, h:used())

    local msgall = zbuff.create(msg:used() + 2, 0)
    msgall:writeU8(0x7e)
    msgall:copy(nil, msg)
    msgall:writeU8(0x7e)
    --  print_zbuff(msgall)

    return msgall
end

function jt808_pos()
    local body = zbuff.create(30, 0)
    local alarm = 0
    body:pack(">I", alarm)
    local status = 0x7C0003
    body:pack(">I", status)

    local lat = pvt_lat
    body:pack(">I", lat)
    local lon = pvt_lon
    body:pack(">I", lon)

    --local alt = 0
    body:pack(">h", pvt_alt)
    --local speed = 0
    body:pack(">h", pvt_speed)
    --local course = 0
    body:pack(">h", pvt_course)

    local date_time = pvt_time
    local l = string.len(date_time)
    for i = 1, l, 2 do

        a = string.sub(date_time, i, i)
        b = string.sub(date_time, i + 1, i + 1)
        local hnum = tonumber(string.sub(date_time, i, i), 16)
        local lnum = tonumber(string.sub(date_time, i + 1, i + 1), 16)

        local num = hnum * 0x10 + lnum
        -- print(string.format("%d %02x", i, num))
        body:writeU8(num)
    end
    local h = header(MSG_POSITION, body:used())
    -- !!!copy will resize the zbuff
    h:copy(nil, body)
    --  crc = proc_crc(h, 0, h:used())
    --  print(crc)
    -- !!!bug
    if h:used() == h:len() then h:resize(h:len() + 10) end

    h:writeU8(proc_crc(h, 0, h:used()))

    local msg = transfer(h, h:used())

    local msgall = zbuff.create(msg:used() + 2, 0)
    msgall:writeU8(0x7e)
    msgall:copy(nil, msg)
    msgall:writeU8(0x7e)
    --  print_zbuff(msgall)

    return msgall
end

function pvt_set(lat, lon, t, alt, speed, course)
    --  print("pvt_set", lat, lon, t, type(lat), type(lon), type(t))
    pvt_lat = lat
    pvt_lon = lon
    pvt_time = t
    pvt_alt=alt;
    pvt_speed=speed
    pvt_course=course
end

init_jt808()
load_param()
--[[
h = header(MSG_HEART, 0)
print("head len: ", h:used())
str=""
for i=0,h:used() - 1 do
  str=str..string.format("%02x ", h[i])
end
print(str)
]] --

--[[
d = jt808_register()
print("reg")
print_zbuff(d)
d=jt808_heart()
print("heart")
print_zbuff(d)
d=jt808_auth()
print("auth")
print_zbuff(d)
cmd = zbuff.create(200)
cmd:write(0x7E,0x81 ,0x00 ,0x40 ,0x0E ,0x01 ,0x00 ,0x00 ,0x00 ,0x00 ,0x01 ,0x30 ,0x62 ,0x50 ,0x90 ,0x65 ,0x00 ,0x01 ,0x00 ,0x01,0x00 ,0x31 ,0x32 ,0x33 ,0x34 ,0x35 ,0x36 ,0x37 ,0x38 ,0x39 ,0x30 ,0x41 ,0x78 ,0x7E )
input_jt808(cmd)
--register()
--register()
]] --

